package cn.good.yan.sf.t3;

import java.util.Iterator;
import java.util.function.Consumer;

/**
 * 3.链表 - 自定义 链表 - 环形链表 - 带哨兵  null 1  2  3  null （互相指引）
 * a 添加头节点（头插法） - addFirst（）
 * b 遍历 （有4种方式 + 递归）
 * c 添加尾节点 （尾插法） - addLast（）
 * d 根据下标获取单条数据 - getIndex
 * e 根据索引添加数据 - addIndex
 * f 删除头元素 - removeFirst
 * g 删除尾元素 - removeLast
 * h 删除指定元素 - （根据下标指定删除元素） - remove
 * i 根据内容判断存不存在 - getValue
 * j 根据值进行删除  - removeValue
 *
 * @author shengren.yan
 * @create 2024-05-02
 */
public class Demo4 implements Iterable<Integer> {

    private static class Node {
        private Node prev; //上一个节点
        private int value; //值
        private Node next; //下一个节点

        public Node(Node prev, int value, Node next) {
            this.prev = prev;
            this.value = value;
            this.next = next;
        }
    }

    private Node head = new Node(null, -11, null);    // 头哨兵

    public Demo4() {
        // 环形
        head.prev = head;
        head.next = head;
    }


    //  a 添加头节点（头插法） - addFirst（）
    public void addFirst(int element) {
        Node next = head.next;
        Node node = new Node(head, element, next);
        head.next = node;
        next.prev = node;
    }

    //  b 遍历 （有4种方式 + 递归）
    // b 遍历 （有1种方式）
    public void loop1() {
        Node n;
        for (n = head.next; n != head; n = n.next) {
            System.out.println(n.value);
        }
    }

    // b 遍历 （有2种方式）
    public void loop2(Consumer<Integer> consumer) {
//        List<Integer> list = Lists.newArrayList();
//        list.stream().forEach();
        Node n;
        for (n = head.next; n != head; n = n.next) {
            consumer.accept(n.value);
        }
    }

    // b 遍历 （有3种方式）
    public void loop3() {
        Node n = head.next;
        while (n != head) {
            System.out.println(n.value);
            n = n.next;
        }
    }

    // b 遍历 （有4种方式）
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Node n = head.next;

            @Override
            public boolean hasNext() {
                return n != head;
            }

            @Override
            public Integer next() {
                int value = n.value;
                n = n.next;
                return value;
            }
        };
    }

    // b 遍历 （有4种方式） - 递归
    public void loop4() {
        re(head.next);
    }

    private void re(Node n) {
        if (n == head) {
            return;
        }
        Node next = n.next;
        System.out.println("前" + n.value);
        re(next);
        System.out.println("后" + n.value);
    }

    // c 添加尾节点 （尾插法） - addLast（）
    public void addLast(int element) {
        Node last = head.prev;
        Node node = new Node(last, element, head);
        last.next = node;
        head.prev = node;
    }

    //  d 根据下标获取单条数据 - getIndex
    public int getIndex(int index) {
        Node node = getNode(index);
        if (node == null || node == head) {
            System.out.println("下标越界");
            return -1;
        }
        return node.value;
    }

    // 根据下标获取元素
    private Node getNode(int index) {
        int i = 0;
        for (Node n = head.next; n != head; n = n.next) {
//            System.out.println(n.value + " - " + i);
            if (i == index) {
                return n;
            }
            i++;
        }
        return null; // 没找到
    }

    // e 根据索引添加数据 - addIndex
    public void addIndex(int index, int element) {
        if (index == 0) {
            addFirst(element);
            return;
        }
        Node node = getNode(index);
        if (node == null) {
            System.out.println("下标越界");
            return;
        }
        Node prev = node.prev;
        Node add = new Node(prev, element, node);
        node.next = add;
        prev.prev = node;
    }

    // f 删除头元素 - removeFirst
    public void removeFirst() {
        Node node = head.next; // 要删除的
        if (node == head) {
            System.out.println("没有要删除的元素");
            return;
        }
        Node next = node.next;
        head.next = next;
        next.prev = head;
    }

    // g 删除尾元素 - removeLast
    public void removeLast() {
        Node last = head.prev; // 要删除的
        if (last == head) {
            System.out.println("没有要删除的元素");
            return;
        }
        Node prev = last.prev;
        prev.next = head;
        head.prev = prev;
    }

    // h 删除指定元素 - （根据下标指定删除元素） - remove
    public void remove(int index) {
        // null 1 2 3
        Node prev = getNode(index - 1);
        if (prev == null) {
            System.out.println("下标越界");
            return;
        }
        Node node = prev.next;  // 被删除的节点
        if (node == head) {
            System.out.println("下标越界");
            return;
        }
        Node next = node.next;
        prev.next = next;
        next.prev = prev;
    }

    // i 根据内容判断存不存在 - getValue
    public boolean getValue(int value) {
        Node node = getValueByNode(value);
        return node != null;
    }

    // 根据值获取元素
    private Node getValueByNode(int value) {
        for (Node n = head.next; n != head; n = n.next) {
            if (n.value == value) {
                return n;
            }
        }
        return null; // 没找到
    }

    //  j 根据值进行删除  - removeValue
    public void removeValue(int value) {
        Node node = getValueByNode(value);
        if (node == null) {
            System.out.println("没有找到");
            return;
        }
        Node prev = node.prev;
        Node next = node.next;
        prev.next = next;
        next.prev = prev;
    }


    public static void main(String[] args) {
        Demo4 d = new Demo4();
        //  a 添加头节点（头插法） - addFirst（）
//        d.addFirst(1);
//        d.addFirst(2);
//        d.addFirst(3);
//        System.out.println(d);
        // b 遍历 （有4种方式 + 递归）
//        d.loop1();
//        d.loop2(x -> {
//            System.out.println(x);
//        });
//        d.loop3();
//        for (Integer e : d) {
//            System.out.println(e);
//        }
//        d.loop4();
        // c 添加尾节点 （尾插法） - addLast（）
//        d.addLast(1);
//        d.addLast(2);
//        d.addLast(3);
//        System.out.println(d);
        // d 根据下标获取单条数据 - getIndex
//        System.out.println(d.getIndex(0));
//        System.out.println(d.getIndex(-1));
//        System.out.println(d.getIndex(1));
//        System.out.println(d.getIndex(2));
//        System.out.println(d.getIndex(3));
        // e 根据索引添加数据 - addIndex
//        d.addIndex(-1, 1);
//        d.addIndex(0, 1);
//        d.addIndex(1, 2);
//        d.addIndex(3, 20);
//        System.out.println(d);

        // f 删除头元素 - removeFirst
//        d.addLast(1);
//        d.addLast(2);
//        d.addLast(3);
//        d.removeFirst();
        // g 删除尾元素 - removeLast
//        d.removeLast();
//        System.out.println(d);
        // h 删除指定元素 - （根据下标指定删除元素） - remove
//        d.remove(0);
//        d.remove(-1);
//        d.remove(1);
//        d.remove(3);
//        System.out.println(d);

        // i 根据内容判断存不存在 - getValue
//        d.addLast(1);
//        d.addLast(2);
//        d.addLast(3);
//        System.out.println(d.getValue(1));
//        System.out.println(d.getValue(0));

        // j 根据值进行删除  - removeValue
        d.addLast(1);
        d.addLast(2);
        d.addLast(3);
        d.removeValue(2);
        System.out.println(d);
    }

}
